﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IsmsExplorer.Infrastructure;
using IsmsExplorer.Model.Documents;
using IsmsExplorer.Infrastructure.RepositoryFramework;
using System.Diagnostics;

namespace IsmsExplorer.Application.Documents {
    public static class DocumentService {
        private static IUnitOfWork _unitOfWork;
        private static IIsmsDocumentLinkRepository _documentLinkRepository;
        private static IIso27001ControlDocumentationRepository _isoControlDocumentRepository;

        static DocumentService() {
            _unitOfWork = new UnitOfWork();
            _documentLinkRepository = RepositoryFactory.GetRepository<IIsmsDocumentLinkRepository, IsmsDocumentLink>(_unitOfWork);
            _isoControlDocumentRepository = RepositoryFactory.GetRepository<IIso27001ControlDocumentationRepository, Iso27001ControlDocumentation>(_unitOfWork);
        }

        /// <summary>
        /// Saves the Iso27001ControlDocumentation object, removing all previous associations of documents with the ISO control
        /// and inserting only the associations present in the supplied Iso27001ControlDocumentation argument.
        /// Use the AddIso27001ControlDocumentation(Iso27001ControlDocumentation doc) if you want to add associations of documents 
        /// to an ISO control.
        /// </summary>
        /// <param name="doc"></param>
        public static void SaveIso27001ControlDocumentation(Iso27001ControlDocumentation doc) {
            if (doc.IsoControl != null) {
                _isoControlDocumentRepository[doc.ProjectID, doc.IsoControl.ID] = doc;
                _unitOfWork.Commit();
            }
        }

        /// <summary>
        /// Associates a number of documents with an ISO control. It will not alter any existing associations.
        /// In contrast with SaveIso27001ControlDocumentation(Iso27001ControlDocumentation doc) which will first
        /// remove any existing associations and then add the new ones.
        /// </summary>
        /// <param name="doc"></param>
        public static void AddIso27001ControlDocumentation(Iso27001ControlDocumentation doc) {
            Debug.Assert(doc != null && doc.ProjectID > 0);
            if (doc.IsoControl != null) {
                // See if documents already exist for the combination project/control.
                Iso27001ControlDocumentation o = _isoControlDocumentRepository[doc.ProjectID, doc.IsoControl.ID];
                if (o != null) {
                    // Documents already exist, merge with new ones and save all.
                    foreach (var isoDoc in o.Documents) {
                        doc.AddDocument(isoDoc);
                    }
                }
                // Call the save method with the updated doc parameter.
                SaveIso27001ControlDocumentation(doc);
            }
        }

        /// <summary>
        /// Disassociates the ISMS documents in the Documents list from the given control and project.
        /// If the Iso27001ControlDocumentation Documents list is empty, this will disassociate ALL the
        /// associated documents for the control for the given project!
        /// </summary>
        /// <param name="doc"></param>
        public static void DeleteIso27001ControlDocumentation(Iso27001ControlDocumentation doc) {
            _isoControlDocumentRepository.Remove(doc);
            _unitOfWork.Commit();
        }

        public static void SaveIsmsDocumentLink(IsmsDocumentLink docLink) {
            if (docLink != null) {
                // The IsmsDocumentLink uses a tuple<int, GUID> as it's primary key (not the int ID field).
                _documentLinkRepository[new Tuple<int, Guid>(docLink.ProjectID, docLink.DocumentID)] = docLink;
                _unitOfWork.Commit();
            }
        }

        /// <summary>
        /// Each document is uniquely identified by a GUID but also the document URL must be unique
        /// within the database table for a particular project. A specific document cannot have two 
        /// different representations unless it is in a different repository.
        /// </summary>
        /// <param name="projectID"></param>
        /// <param name="documentUrl"></param>
        /// <param name="repositoryTypeID"></param>
        /// <returns></returns>
        public static IsmsDocumentLink FindByUrlInRepository(int projectID, string documentUrl, int repositoryTypeID) {
            return _documentLinkRepository.FindByUrlInRepository(projectID, documentUrl, repositoryTypeID);
        }

        public static IList<IsmsDocumentLink> GetAllIsmsDocumentLinksForProject(int projectID) {
            return _documentLinkRepository.GetAllIsmsDocumentLinksForProject(projectID);
        }

        public static void DeleteIsmsDocumentLink(IsmsDocumentLink docLink) {
            _documentLinkRepository.Remove(docLink);
            _unitOfWork.Commit();
        }

    } // end public static class DocumentService
}
